#ifndef BLOQUE_H_
#define BLOQUE_H_

#include <list>
#include "Componente.h"
#include "Clave.h"

namespace Toolkit
{

class Bloque: public Componente
{
public:
    Bloque(const unsigned long int &tamanoBloque, const TipoSerializacion&);

    virtual ~Bloque();

    virtual void serializar(stringstream&) const;
    virtual void hidratar(stringstream &stream, const Dato &dato);

    /**
     * Si hay suficiente espacio, se agrega el bloque indicado
     * a los componentes del bloque. Si no se devuelve false.
     * EL BLOQUE QUEDA COMO OWNER DE LA MEMORIA, SALVO QUE SE RETIRE
     * EL COMPONENTE MAS TARDE.
     * */
    virtual void agregar(Componente*, const Clave&);

    /**
     * Retira del bloque el elemento cuya clave es pasada y lo retorna.
     * Si no se encuentra el elemento, se devuelve NULL.
     * SE DEBE LIBERAR LA MEMORIA TRAS UTILIZARLO
     * */
    Componente* remover(const Clave&);

    /**
     * Devuelve el elemento del bloque con la clave pasada,
     * o NULL de no encontrarlo.
     * */
    virtual Componente* buscar(const Clave&);

    /**
     * Devuelve el espacio, en bytes, que queda libre en el bloque.
     * Esto es, se podra agregar al bloque cualquier elemento
     * cuya serializacion tenga un tamano menor al devuelto.
     * */
    virtual long int espacioLibre() const;
    /**
     * Devuelve el tamano del bloque, en bytes.
     * */
    unsigned long int getTamanoBloque() const;

    /**
    * Devuelve true si el agregado de el bloque pasado no provocaría
    * un desborde del bloque.
    **/
    bool puedeAgregarse(Componente *componente);

    /**
     * Devuelve true, si la clave mas grande de los elementos del
     * bloque es menor a la clave pasada.
     * */
    virtual bool operator <(const Clave&) const;
    /**
     * Devuelve true si la clave pasada coincide con la mayor clave
     * de los elementos del bloque.
     * */
    virtual bool operator ==(const Clave&) const;

    virtual int cantElementos() const;

    Componente* popBack();
    Componente* popFront();

    virtual char getTipo() const;

    virtual Componente *clonar() const;

    virtual list<Clave*> getClaves(const Clave &claveMolde) const;


protected:
    /* Tamano en bytes del identificador que se coloca en la serializacion antes
     * de cada elemento.*/
    unsigned long int tamanoBloque;
    list<Componente*> componentes;

    void agregarSinChequearMaximo(Componente*, const Clave&);

    virtual string especializarSerializacion() const;
    virtual void especializarHidratacion(stringstream&);
};

}

#endif /* BLOQUE_H_ */
